package com.alex.taskmanager.dispatcher;

import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alex.taskmanager.dao.TaskData;
import com.alex.taskmanager.dao.TaskManagerDao;
import com.alex.taskmanager.service.TaskRunnerFactory;
import com.alex.taskmanager.threadpool.ThreadPool;
import com.alex.taskmanager.threadpool.WorkerThread;
import com.alex.taskmanager.threadpool.WorkerWithLogging;

public class TaskDispatcher {

	private static final Logger LOGGER = LoggerFactory.getLogger(TaskDispatcher.class);

	private WorkerThread thread;

	private TaskManagerDao taskManagerDao;
	
	private TaskRunnerFactory taskRunnerFactory;

	private ThreadPool threadPool;

	private int sleepDuration = 5000;

	public TaskDispatcher(TaskRunnerFactory taskRunnerFactory, TaskManagerDao taskManagerDao, ThreadPool threadPool) {
		this.taskRunnerFactory = taskRunnerFactory;
		this.taskManagerDao = taskManagerDao;
		this.threadPool = threadPool;
	}

	public void start() {
		thread = new WorkerThread(new TaskDispatcherWorker(), "TaskManagerDispatcherThread");
		thread.start();
	}

	public void stop() throws InterruptedException {
		thread.stopThread();
		thread.interrupt();
		thread.join();
	}
	
	public boolean hasExecutingTasks() {
		return threadPool.getCurrentTaskCount() > 0;
	}

	class TaskDispatcherWorker extends WorkerWithLogging {

		public void run() throws Exception {
			int remainingTaskCapacity = threadPool.getRemainingTaskCapacity();
			if (remainingTaskCapacity == 0) {
				Thread.sleep(sleepDuration);
			} else {
				Collection<TaskData<Object>> tasks = taskManagerDao.getTasks(remainingTaskCapacity, (int) (System.currentTimeMillis() / 1000));
				for (final TaskData<Object> taskData : tasks) {
					threadPool.addTask(taskRunnerFactory.getTaskRunner(taskData));
				}
			}
		}

		@Override
		public Logger getLogger() {
			return LOGGER;
		}
	}
}
